import axios, {
  AxiosInstance,
  AxiosRequestConfig,
  AxiosResponse,
  AxiosError,
  CancelTokenSource,
} from "axios";
import { useState, useEffect, useRef, useCallback } from "react";

// 定义基础响应类型
interface BaseResponse<T = any> {
  code: number;
  status: number;
  data: T;
  message: string;
}

// 自定义配置
interface RequestOptions {
  manual?: boolean; // 是否手动触发
  debounce?: number; // 防抖时间(ms)
  retry?: number; // 重试次数
  loadingDelay?: number; // 延迟显示加载时间(ms)
}

// 封装后的请求Hook返回类型
interface RequestResult<T> {
  data: T | null;
  loading: boolean;
  error: AxiosError | null;
  run: (params?: any) => Promise<void>;
  cancel: () => void;
}

// 创建Axios实例
const createService = (): AxiosInstance => {
  const service = axios.create({
    // baseURL: process.env.REACT_APP_API_BASE_URL,
    baseURL: "http://localhost:3000",
    timeout: 10000,
    headers: {
      "Content-Type": "application/json",
    },
  });

  // 请求拦截器
  service.interceptors.request.use(
    (config) => {
      // 添加认证token
      const token = localStorage.getItem("access_token");
      if (token) {
        config.headers.Authorization = `Bearer ${token}`;
      }
      return config;
    },
    (error) => Promise.reject(error)
  );

  // 响应拦截器
  service.interceptors.response.use(
    (response) => {
      // 统一处理响应数据

      if (response.data.code !== 200) {
        return Promise.reject(response.data);
      }
      return response.data;
    },
    (error) => {
      // 统一错误处理
      if (error.response) {
        switch (error.response.status) {
          case 401:
            // 处理未授权
            break;
          case 403:
            // 处理禁止访问
            break;
          case 500:
            // 处理服务器错误
            break;
        }
      }
      return Promise.reject(error);
    }
  );

  return service;
};

const service = createService();

// 请求缓存
const pendingRequests = new Map();

// 生成请求唯一标识
const generateReqKey = (config: AxiosRequestConfig): string => {
  return `${config.url}&${config.method}`;
};

// 添加请求到缓存
const addPendingRequest = (config: AxiosRequestConfig) => {
  const key = generateReqKey(config);
  const source = axios.CancelToken.source();
  config.cancelToken = source.token;
  if (!pendingRequests.has(key)) {
    pendingRequests.set(key, source);
  }
};

// 移除缓存请求
const removePendingRequest = (config: AxiosRequestConfig) => {
  const key = generateReqKey(config);
  if (pendingRequests.has(key)) {
    const source = pendingRequests.get(key);
    source.cancel("Request canceled by duplicate prevention");
    pendingRequests.delete(key);
  }
};

// 自定义请求Hook
const useRequest = <T = any>(
  config: AxiosRequestConfig,
  options: RequestOptions = {}
): RequestResult<T> => {
  const {
    manual = false,
    debounce = 0,
    retry = 0,
    loadingDelay = 300,
  } = options;
  const [data, setData] = useState<T | null>(null);
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState<AxiosError | null>(null);
  const retryCountRef = useRef(0);
  const cancelTokenSourceRef = useRef<CancelTokenSource | null>(null);
  const timerRef = useRef<NodeJS.Timeout | null>(null);
  const loadingTimerRef = useRef<NodeJS.Timeout | null>(null);

  // 实际执行请求的函数
  const fetchData = useCallback(
    async (params?: any) => {
      // 合并参数
      const requestConfig = { ...config };
      if (params) {
        if (requestConfig.method?.toLowerCase() === "get") {
          requestConfig.params = params;
        } else {
          requestConfig.data = params;
        }
      }

      // 取消重复请求
      removePendingRequest(requestConfig);
      addPendingRequest(requestConfig);

      // 创建取消令牌
      const source = axios.CancelToken.source();
      cancelTokenSourceRef.current = source;
      requestConfig.cancelToken = source.token;

      // 延迟显示loading
      loadingTimerRef.current = setTimeout(() => {
        setLoading(true);
      }, loadingDelay);

      try {
        const response = (await service(requestConfig)) as AxiosResponse<
          BaseResponse<T>
        >;
        // console.log(response.data);

        setData(response.data);
        setError(null);
        retryCountRef.current = 0;
      } catch (err) {
        const axiosError = err as AxiosError;
        // 非主动取消的错误
        if (!axios.isCancel(axiosError)) {
          setError(axiosError);

          // 重试逻辑
          if (retryCountRef.current < retry) {
            retryCountRef.current += 1;
            setTimeout(() => fetchData(params), 1000 * retryCountRef.current);
          }
        }
      } finally {
        // 清除loading计时器
        if (loadingTimerRef.current) {
          clearTimeout(loadingTimerRef.current);
          loadingTimerRef.current = null;
        }
        setLoading(false);

        // 从缓存中移除请求
        const key = generateReqKey(requestConfig);
        pendingRequests.delete(key);
      }
    },
    [config, loadingDelay, retry]
  );

  // 防抖处理
  const run = useCallback(
    (params?: any) => {
      return new Promise<void>((resolve, reject) => {
        if (timerRef.current) {
          clearTimeout(timerRef.current);
        }

        timerRef.current = setTimeout(async () => {
          try {
            await fetchData(params);
            resolve();
          } catch (err) {
            reject(err);
          }
        }, debounce);
      });
    },
    [fetchData, debounce]
  );

  // 取消请求
  const cancel = useCallback(() => {
    if (cancelTokenSourceRef.current) {
      cancelTokenSourceRef.current.cancel("Request canceled by user");
    }
    if (timerRef.current) {
      clearTimeout(timerRef.current);
      timerRef.current = null;
    }
    if (loadingTimerRef.current) {
      clearTimeout(loadingTimerRef.current);
      loadingTimerRef.current = null;
    }
    setLoading(false);
  }, []);

  // 组件卸载时取消请求
  useEffect(() => {
    return () => {
      cancel();
    };
  }, [cancel]);

  // 自动执行请求
  useEffect(() => {
    if (!manual) {
      run();
    }
  }, [manual, run]);

  return { data, loading, error, run, cancel };
};

export default useRequest;
